﻿#import string

import xml.sax

from xml.sax.handler import *

import ogre.renderer.OGRE as ogre 

ignore = '#'


class _DefaultHandler():

	def __init__(self,parent = None,root = None):
		self.parent = parent
		self.root = root
		pass

	def start(self,attrs):
		s = ''
		for i in attrs.items():
			s += `i`
		return s
		pass

	def end(self):
		pass

	pass

class sceneHandler():
	def __init__(self,parent = None,root = None):
		self.parent = parent
		#self.root = root
		pass

	def start(self,attrs):
		assert attrs.get('formatVersion', None) == '1.0'
		assert attrs.get('upAxis', None) == 'y'
		assert attrs.get('unitsPerMeter', None)	== '1'
		assert attrs.get('minOgreVersion', None) == '1.7'
		#attrs.get('author', None)
		#attrs.get('application', None)
		pass

	def end(self):
		pass

	def save(self,sm,plugins,parent,doc):
		e = doc.createElement("scene")
		doc.appendChild(e)

		e.setAttribute("formatVersion", '1.0')
		e.setAttribute("upAxis", 'y')
		e.setAttribute("unitsPerMeter", '1')
		e.setAttribute("minOgreVersion", '1.7')

		environmentHandler().save(sm, e, doc)
		nodesHandler().save(sm, e, doc)

		if plugins:
			pluginsHandler().save(plugins,sm, e, doc)
		pass
	pass

class environmentHandler():

	def __init__(self,parent = None,root = None):
		self.parent = parent
		self.root = root
		pass

	def start(self,attrs):
		pass

	def end(self):
		pass

	def save(self,sm,parent,doc):
		e = doc.createElement("environment")
		parent.appendChild(e)

		colourAmbientHandler().save(sm, e, doc)
		colourBackgroundHandler().save(sm, e, doc)
		fogHandler().save(sm, e, doc)
		pass

	pass

	
class colourAmbientHandler():

	def __init__(self,parent = None,root = None):
		self.parent = parent
		self.root = root
		pass

	def start(self,attrs):
		if self.root.sm :
			r = float(attrs.get('r', None))
			g = float(attrs.get('g', None))
			b = float(attrs.get('b', None))

			c = ogre.ColourValue(r,g,b)
			self.root.sm.setAmbientLight(c)
		pass

	def end(self):
		pass

	def save(self,sm,parent,doc):
		e = doc.createElement("colourAmbient")
		parent.appendChild(e)

		c = sm.getAmbientLight()
		e.setAttribute("r", `c.r`)
		e.setAttribute("g", `c.g`)
		e.setAttribute("b", `c.b`)
		pass

	pass


class colourBackgroundHandler():

	def __init__(self,parent = None,root = None):
		self.parent = parent
		self.root = root
		pass

	def start(self,attrs):
		if self.root.sm :
			r = float(attrs.get('r', None))
			g = float(attrs.get('g', None))
			b = float(attrs.get('b', None))

			c = ogre.ColourValue(r,g,b)

			# //Set all viewports to the specified background color
			# if (this->renderWindows->Start())
			# {
				# do
				# {
					# RenderWindow* renderWindow = this->renderWindows->GetCurrent();
					# unsigned short viewportCount = renderWindow->getNumViewports();
					# for (unsigned short viewportIndex = 0; viewportIndex < viewportCount; viewportIndex++)
						# renderWindow->getViewport(viewportIndex)->setBackgroundColour(backgroundColor);
				# }while (this->renderWindows->MoveNext());
			# }
		pass

	def end(self):
		pass

	def save(self,sm,parent,doc):
		pass

	pass

class fogHandler():

	def __init__(self,parent = None,root = None):
		self.parent = parent
		self.root = root
		pass

	def start(self,attrs):
		if self.root.sm :
			self.mode = attrs.get('mode', None)
			if self.mode == 'exp' :
				self.mode = ogre.FogMode.FOG_EXP
			elif self.mode == 'exp2' :
				self.mode = ogre.FogMode.FOG_EXP2
			elif self.mode == 'linear' :
				self.mode = ogre.FogMode.FOG_LINEAR
			else :
				self.mode = ogre.FogMode.FOG_NONE
				
			self.ed = float(attrs.get('expDensity', None))
			self.ls = float(attrs.get('linearStart', 0.0))
			self.le = float(attrs.get('linearEnd', 0.0))
		pass

	def end(self):
		self.root.sm.setFog(self.mode, self.cd, self.ed, self.ls, self.le)
		pass

	def save(self,sm,parent,doc):
		if sm.getFogMode() == ogre.FogMode.FOG_NONE :
			return

		e = doc.createElement("fog")
		parent.appendChild(e)

		m = "none"
		if sm.getFogMode() == ogre.FogMode.FOG_EXP :
			m = 'exp'
		elif sm.getFogMode() == ogre.FogMode.FOG_EXP2 :
			m = 'exp2'
		elif sm.getFogMode() == ogre.FogMode.FOG_LINEAR :
			m = 'linear'

		e.setAttribute("mode", 			m)
		e.setAttribute("expDensity", 	`sm.getFogDensity()`)
		e.setAttribute("linearStart", 	`sm.getFogStart()`)
		e.setAttribute("linearEnd", 	`sm.getFogEnd()`)
		colourDiffuseHandler().save(sm.getFogColour(),e,doc)
		pass

	pass

class colourDiffuseHandler():

	def __init__(self,parent = None,root = None):
		self.parent = parent
		self.root = root
		pass

	def start(self,attrs):
		if self.root.sm :
			r = float(attrs.get('r', None))
			g = float(attrs.get('g', None))
			b = float(attrs.get('b', None))

			self.parent.cd = ogre.ColourValue(r,g,b)
		pass

	def end(self):
		pass

	def save(self,c,parent,doc):
		e = doc.createElement("colourDiffuse")
		parent.appendChild(e)

		e.setAttribute("r", `c.r`)
		e.setAttribute("g", `c.g`)
		e.setAttribute("b", `c.b`)
		pass

	pass

class colourSpecularHandler():

	def __init__(self,parent = None,root = None):
		self.parent = parent
		self.root = root
		pass

	def start(self,attrs):
		if self.root.sm :
			r = float(attrs.get('r', None))
			g = float(attrs.get('g', None))
			b = float(attrs.get('b', None))

			self.parent.cs = ogre.ColourValue(r,g,b)
		pass

	def end(self):
		pass

	def save(self,c,parent,doc):
		e = doc.createElement("colourSpecular")
		parent.appendChild(e)

		e.setAttribute("r", `c.r`)
		e.setAttribute("g", `c.g`)
		e.setAttribute("b", `c.b`)
		pass

	pass

class lightAttenuationHandler():

	def __init__(self,parent = None,root = None):
		self.parent = parent
		self.root = root
		pass

	def start(self,attrs):
		if self.root.sm :
			self.parent.range 		= float(attrs.get('range', None))
			self.parent.constant 	= float(attrs.get('constant', None))
			self.parent.linear 		= float(attrs.get('linear', None))
			self.parent.quadric 	= float(attrs.get('quadric', None))
		pass

	def end(self):
		pass

	def save(self,l,parent,doc):
		e = doc.createElement("lightAttenuation")
		parent.appendChild(e)

		e.setAttribute("range", 	`l.getAttenuationRange()`)
		e.setAttribute("constant", 	`l.getAttenuationConstant()`)
		e.setAttribute("linear", 	`l.getAttenuationLinear()`)
		e.setAttribute("quadric", 	`l.getAttenuationQuadric()`)
		pass

	pass

class shadowsHandler():

	def __init__(self,parent = None,root = None):
		self.parent = parent
		self.root = root
		pass

	def start(self,attrs):
		if self.root.sm :
			r = attrs.get('technique', None)
			g = float(attrs.get('farDistance', None))
		pass

	def end(self):
		pass

	def save(self,sm,parent,doc):
		pass

	pass

class nodesHandler():
	def __init__(self,parent = None,root = None):
		self.parent = parent
		self.root = root
		self.scene_node = None

		if root and root.sm :
			self.scene_node = root.sm.getRootSceneNode()
		pass

	def start(self,attrs):
		pass

	def end(self):
		pass

	def save(self,sm,parent,doc):
		e = doc.createElement("nodes")
		parent.appendChild(e)
		
		for n in sm.getRootSceneNode().getChildIterator():
			nodeHandler().save(n.castAsSceneNode(),e,doc)
		pass
	pass

class nodeHandler():
	node_num = 0
	def __init__(self,parent = None,root = None):
		self.parent = parent
		self.root = root

		self.scene_node = None
		pass

	def start(self,attrs):
		if self.parent.scene_node:
			n = attrs.get('name', None)
			self.scene_node = self.parent.scene_node.createChildSceneNode(n)
		pass

	def end(self):
		self.scene_node.setPosition(self.position)
		self.scene_node.setScale(self.scale)
		self.scene_node.setOrientation(self.rotation)
		
		nodeHandler.node_num += 1
		pass

	def save(self,sn,parent,doc):
		if sn.getName()[0] == ignore :
			return
		
		e = doc.createElement("node")
		parent.appendChild(e)

		e.setAttribute("name", 	sn.getName())
		positionHandler().save(sn.getPosition(),e,doc)
		scaleHandler().save(sn.getScale(),e,doc)
		rotationHandler().save(sn.getOrientation(),e,doc)

		for mo in sn.getAttachedObjectIterator():
			if mo.getMovableType() == 'Entity' :
				entityHandler().save(mo,e,doc)
			elif mo.getMovableType() == 'Light' :
				lightHandler().save(mo,e,doc)
			else : #to do ...
				#assert(False)
				print "this MovableObject type can'n save :",mo.getMovableType()
				pass

		for n in sn.getChildIterator():
			nodeHandler().save(n.castAsSceneNode(),e,doc)
		pass

	pass

class positionHandler():
	def __init__(self,parent = None,root = None):
		self.parent = parent
		pass

	def start(self,attrs):
		x = float(attrs.get('x', None))
		y = float(attrs.get('y', None))
		z = float(attrs.get('z', None))
		self.parent.position = ogre.Vector3(x,y,z)
		pass

	def end(self):
		pass

	def save(self,p,parent,doc):
		e = doc.createElement("position")
		parent.appendChild(e)

		e.setAttribute("x", `p.x`)
		e.setAttribute("y", `p.y`)
		e.setAttribute("z", `p.z`)
		pass

class scaleHandler():
	def __init__(self,parent = None,root = None):
		self.parent = parent
		pass

	def start(self,attrs):
		x = float(attrs.get('x', None))
		y = float(attrs.get('y', None))
		z = float(attrs.get('z', None))
		self.parent.scale = ogre.Vector3(x,y,z)
		pass

	def end(self):
		pass
	
	def save(self,s,parent,doc):
		e = doc.createElement("scale")
		parent.appendChild(e)

		e.setAttribute("x", `s.x`)
		e.setAttribute("y", `s.y`)
		e.setAttribute("z", `s.z`)
		
		pass

class rotationHandler():
	def __init__(self,parent = None,root = None):
		self.parent = parent
		pass

	def start(self,attrs):
		x = float(attrs.get('qx', None))
		y = float(attrs.get('qy', None))
		z = float(attrs.get('qz', None))
		w = float(attrs.get('qw', None))
		self.parent.rotation = ogre.Quaternion(w,x,y,z)
		pass

	def end(self):
		pass
	
	def save(self,o,parent,doc):
		e = doc.createElement("rotation")
		parent.appendChild(e)

		e.setAttribute("qx", `o.x`)
		e.setAttribute("qy", `o.y`)
		e.setAttribute("qz", `o.z`)
		e.setAttribute("qw", `o.w`)
		pass

class entityHandler():
	entity_num = 0
	def __init__(self,parent = None,root = None):
		self.parent = parent
		self.root = root
		self.entity = None
		pass

	def start(self,attrs):
		if self.parent.scene_node:
			n = attrs.get('name', None)
			c = bool(attrs.get('castShadows', None))
			#r = float(attrs.get('receiveShadows', None))
			m = attrs.get('meshFile', None)
			rd = float(attrs.get('renderingDistance', 0.0))

			#entity.setQueryFlags
			#entity.setVisibilityFlags

			entity = self.root.sm.createEntity(n, m);
			entity.setCastShadows(c)
			entity.setRenderingDistance(rd)

			self.parent.scene_node.attachObject(entity)
		pass

	def end(self):
		entityHandler.entity_num += 1
		pass
	

	def save(self,ent,parent,doc):
		if ent.getName()[0] == ignore :
			return

		e = doc.createElement("entity")
		parent.appendChild(e)

		e.setAttribute("name", 			ent.getName())
		e.setAttribute("castShadows", 	`ent.getCastShadows()`)
		e.setAttribute("meshFile", 		ent.getMesh().getName())
		e.setAttribute("renderingDistance", `ent.getRenderingDistance()`)

		if ent.getVisible() == False :
			e.setAttribute("visible", `ent.getVisible()`)
		if ent.getVisibilityFlags() != 4294967295L :
			e.setAttribute("visibilityFlags", `ent.getVisibilityFlags()`)
		if ent.getQueryFlags() != 4294967295L :
			e.setAttribute("queryFlags", `ent.getQueryFlags()`)


		subentitiesHandler().save(ent,e,doc)
		pass

class subentitiesHandler():
	def __init__(self,parent = None,root = None):
		self.parent = parent
		#self.root = root
		pass

	def start(self,attrs):
		pass

	def end(self):
		pass

	def save(self,ent,parent,doc):
		e = doc.createElement("subentities")
		parent.appendChild(e)
		
		for i in range(0,ent.getNumSubEntities()):
			subentityHandler().save(ent,i,e,doc)
		pass
	pass

class subentityHandler():
	def __init__(self,parent = None,root = None):
		self.parent = parent
		self.root = root
		pass

	def start(self,attrs):
			i = int(attrs.get('index', None))
			m = attrs.get('materialName', None)

			e = self.parent.parent.entity
			if e :
				subentity = e.getSubEntity(i)
				if m != '':
					subentity.setMaterialName(m);


	def end(self):
		pass

	def save(self,ent,i,parent,doc):
		e = doc.createElement("subentity")
		parent.appendChild(e)
		
		e.setAttribute("index",`i`)
		e.setAttribute("materialName",ent.getSubEntity(i).getMaterialName())
		pass
	pass

class lightHandler():

	def __init__(self,parent = None,root = None):
		self.parent = parent
		self.root = root
		pass

	def start(self,attrs):
		if self.root.sm :
			self.name 			= attrs.get('name', None)
			#self.visible 		= attrs.get('visible', None)
			self.type 			= attrs.get('type', None)
			self.castShadows 	= attrs.get('castShadows', None)
			self.power 			= float(attrs.get('power', None))

			if self.type == 'point' :
				self.type = ogre.Light.LightTypes.LT_POINT
			elif self.type == 'directional' :
				self.type = ogre.Light.LightTypes.LT_DIRECTIONAL
			elif self.type == 'spot' :
				self.type = ogre.Light.LightTypes.LT_SPOTLIGHT
			else:
				assert(None)

			if self.castShadows == 'false' :
				self.castShadows = False
			else :
				self.castShadows = True

		pass

	def end(self):
		light = self.root.sm.createLight(self.name)
		#light.setQueryFlags
		#light.setVisibilityFlags
		light.setType(self.type)
		light.setCastShadows(self.castShadows)
		light.setPowerScale(self.power)
		light.setDiffuseColour(self.cd)
		light.setSpecularColour(self.cs)
		if self.type == ogre.Light.LightTypes.LT_SPOTLIGHT :
			light.setSpotlightInnerAngle(self.inner)
			light.setSpotlightOuterAngle(self.outer)
			light.setSpotlightFalloff(self.falloff)
		light.setAttenuation(self.range, self.constant, self.linear, self.quadric)
		#light.setPosition
		#light.setDirection

		self.parent.scene_node.attachObject(light)
		pass

	def save(self,l,parent,doc):
		e = doc.createElement("light")
		parent.appendChild(e)

		e.setAttribute("name",l.getName())

		if l.getVisible() == False :
			e.setAttribute("visible", `l.getVisible()`)
		if l.getVisibilityFlags() != 4294967295L :
			e.setAttribute("visibilityFlags", `l.getVisibilityFlags()`)
		if l.getQueryFlags() != 4294967295L :
			e.setAttribute("queryFlags", `l.getQueryFlags()`)

		t = "none"
		if l.getType() == ogre.Light.LightTypes.LT_POINT :
			t = 'point'
		elif l.getType() == ogre.Light.LightTypes.LT_DIRECTIONAL :
			t = 'directional'
		elif l.getType() == ogre.Light.LightTypes.LT_SPOTLIGHT :
			t = 'spot'
			
		
		e.setAttribute("type",t)
		e.setAttribute("castShadows",`l.getCastShadows()`)
		e.setAttribute("power",`l.getPowerScale()`)
		if l.getType() == ogre.Light.LightTypes.LT_SPOTLIGHT :
			e.setAttribute("inner",l.getSpotlightInnerAngle())
			e.setAttribute("outer",l.getSpotlightOuterAngle())
			e.setAttribute("falloff",l.getSpotlightFalloff())

		colourDiffuseHandler().save(l.getDiffuseColour(),e,doc)
		colourSpecularHandler().save(l.getSpecularColour(),e,doc)
		lightAttenuationHandler().save(l,e,doc)
		pass

	pass

class skyBoxHandler():

	def __init__(self,parent = None,root = None):
		self.parent = parent
		self.root = root
		pass

	def start(self,attrs):
		self.material 	= attrs.get('material', None)
		self.enable 	= bool(attrs.get('enable', None))
		self.distance 	= float(attrs.get('distance', None))
		self.drawFirst 	= bool(attrs.get('drawFirst', None))
		pass

	def end(self):
		self.root.sm.setSkyBox(self.enable,self.material,self.distance,self.drawFirst,self.rotation)
		pass

	def save(self,sm,i,parent,doc):
		e = doc.createElement("skyBox")
		parent.appendChild(e)

		m = ''
		df = True
		sm.getSkyBoxNode()
		for mo in sm.getSkyBoxNode().getAttachedObjectIterator():
			m = mo.getSubEntity(0).getMaterialName()
			df = mo.getRenderQueueGroup() == ogre.RenderQueueGroupID.RENDER_QUEUE_SKIES_EARLY

		e.setAttribute("material",m)
		e.setAttribute("enable",sm.isSkyBoxEnabled())
		e.setAttribute("distance",sm.getSkyBoxGenParameters().skyBoxDistance)
		e.setAttribute("drawFirst",df)
		
		pass

class pluginsHandler():

	def __init__(self,parent = None,root = None):
		self.parent = parent
		self.root = root
		#self.sm = sm
		#self.plugins = parent.plugins
		pass

	def start(self,attrs):
		pass

	def end(self):
		pass

	def save(self,plugins,sm,parent,doc):
		e = doc.createElement("plugins")
		parent.appendChild(e)

		for p in dir(plugins):
			pp = getattr(plugins,p)
			if hasattr(pp,'ICreateXMLHandler'):
				pp.ICreateXMLHandler().save(sm,e,doc)
		pass

	def createHandler(self,name,parent,root):
		p = getattr(root.plugins,name)
		return p.ICreateXMLHandler(parent,root)



class XmlSceneLoadHandler(ContentHandler):

	def __init__(self,sm,plugins):
		self.di_gui_num = 0	##节点深度
		self.curr_handler = self
		self.sm = sm
		self.plugins = plugins
		pass

	def tab_str(self):
		tab_c = ''
		for i in range(0,self.di_gui_num):
			tab_c += '  '
		return tab_c


	def startDocument(self):
		print '--- start Document ---'

		ogreroot = ogre.Root.getSingleton()
		if ogreroot == None:
			print 'err: ogreroot == None'
			return

	def endDocument(self):
		print '---  end Document  ---'


	def startElement(self, name, attrs):
		self.di_gui_num += 1

		print self.tab_str() + '<< startElement:',name

		try:
			exec 'self.curr_handler = ' + name + 'Handler(self.curr_handler,self)' 
		except Exception as inst:
			if hasattr(self.curr_handler,'createHandler'):
				new_handler = self.curr_handler.createHandler(name,self.curr_handler,self)
				if new_handler :
					self.curr_handler = new_handler
				else:
					self.curr_handler = self._CreateDefaultHandler(name)
			else:
			#print self.tab_str(),inst
				self.curr_handler = self._CreateDefaultHandler(name)

		if self.curr_handler != self:
			s = self.curr_handler.start(attrs)
			if s != None and len(s) != 0 :
				print self.tab_str() + s

		pass

	def _CreateDefaultHandler(self,name):
		print "error > can't find element handler :", name
		return _DefaultHandler(self.curr_handler,self)


	def endElement(self, name):

		if self.curr_handler != self:
			s = self.curr_handler.end()
			if s != None and len(s) != 0 :
				print self.tab_str() + s

			self.curr_handler = self.curr_handler.parent
		else:
			print self.tab_str() + '>> endElement: ',name

		self.di_gui_num -= 1
		pass

	def characters(self, ch):
		return
		if self.curr_handler != self:
			self.curr_handler.characters(ch)

		if ch == None:
			print '  ' + self.tab_str() + 'characters: ',ch

		print '  ' + self.tab_str() + 'di gui num: ',self.di_gui_num

		pass

	
def load(scene_file,sm,plugins = None):
	#
	strs = scene_file.split('\\')
	rl = ''
	for i in range(0,len(strs)-1) :
		rl += strs[i] + '\\'

	print 'scene file : ', scene_file
	print 'resource location : ',rl
	print 'res group name : ',strs[len(strs)-1]
	ogre.ResourceGroupManager.getSingleton().addResourceLocation(rl, "FileSystem", scene_file, False)
	ogre.ResourceGroupManager.getSingleton().initialiseResourceGroup(scene_file)


	parser = xml.sax.make_parser()

	handler = XmlSceneLoadHandler(sm,plugins)

	parser.setContentHandler(handler)

	parser.parse(scene_file)

	print '---------------------------------------------'
	print 'node num 	:',nodeHandler.node_num
	print 'entity num 	:',entityHandler.entity_num
	print '---------------------------------------------'
	pass


def save(scene_file,sm,plugins = None,ignore = '#'):
	from xml.dom.minidom import Document
	doc = Document()
	sceneHandler().save(sm, plugins,None, doc)

	f=file(scene_file, 'w')
	doc.writexml(f, '','	','\n',encoding='utf-8')
	f.close()
	pass

##
if __name__ == '__main__':
	load("F:\\OgreEditor\\test\\scene0.scene")











